using UniversalAdmin.Application.Common;
using UniversalAdmin.Application.DTOs;
using UniversalAdmin.Application.Services;
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Domain.Enums;
using UniversalAdmin.Domain.Interfaces;
using UniversalAdmin.Domain.Repositories;

namespace UniversalAdmin.Infrastructure.Services;

public class ArticleService : IArticleService
{
  private readonly IUnitOfWork _uow;
  private readonly IArticleRepository _articleRepo;

  public ArticleService(IUnitOfWork uow, IArticleRepository articleRepo)
  {
    _uow = uow;
    _articleRepo = articleRepo;
  }

  public async Task<PagedResult<ArticleListDto>> GetArticlesAsync(
      string? keyword, int? categoryId, ArticleStatus? status, int pageIndex, int pageSize)
  {
    var (items, total) = await _articleRepo.GetPagedArticlesAsync(keyword, categoryId, status, pageIndex, pageSize);
    var dtos = items.Select(a => new ArticleListDto
    {
      Id = a.Id,
      Title = a.Title,
      Summary = a.Summary,
      Status = a.Status.ToString(),
      CategoryName = a.Category?.Name,
      AuthorName = a.User?.Username ?? "未知",
      CreatedAt = a.CreatedAt
    });

    return new PagedResult<ArticleListDto>
    {
      Items = dtos.ToList(),
      TotalCount = total,
      PageIndex = pageIndex,
      PageSize = pageSize
    };
  }

  public async Task<ArticleDto?> GetArticleByIdAsync(int id)
  {
    var article = await _articleRepo.GetByIdAsync(id);
    if (article == null) return null;

    return new ArticleDto
    {
      Id = article.Id,
      Title = article.Title,
      Content = article.Content,
      Summary = article.Summary,
      Status = article.Status,
      CategoryId = article.CategoryId,
      CategoryName = article.Category?.Name,
      UserId = article.UserId,
      AuthorName = article.User?.Username ?? "未知",
      CreatedAt = article.CreatedAt,
      UpdatedAt = article.UpdatedAt
    };
  }

  public async Task<PagedResult<ArticleDto>> SearchArticlesAsync(
    ArticleQueryParameters p,
    CancellationToken ct = default)
  {
    var (items, total) = await _articleRepo.SearchArticlesAsync(
        keyword: p.Keyword,
        status: p.Status,
        start: p.Start,
        end: p.End,
        pageIndex: p.Page,
        pageSize: p.Size,
        ct);

    var dtos = items.Select(a => new ArticleDto
    {
      Id = a.Id,
      Title = a.Title,
      Content = a.Content,
      Summary = a.Summary,
      Status = a.Status,
      CategoryId = a.CategoryId,
      CategoryName = a.Category?.Name,
      UserId = a.UserId,
      AuthorName = a.User?.Username ?? "anonymous",
      CreatedAt = a.CreatedAt,
      UpdatedAt = a.UpdatedAt
    }).ToList();

    return new PagedResult<ArticleDto>
    {
      Items = dtos,
      TotalCount = total,
      PageIndex = p.Page,
      PageSize = p.Size
    };
  }

  public async Task<ArticleDto> CreateArticleAsync(CreateArticleDto dto, int userId)
  {
    var article = Article.Create(dto.Title, dto.Content, dto.Summary, userId, dto.Status, dto.CategoryId);
    await _articleRepo.AddAsync(article);
    await _uow.SaveChangesAsync();
    return await GetArticleByIdAsync(article.Id) ?? throw new Exception("创建失败");
  }

  public async Task<ArticleDto> UpdateArticleAsync(
      int id, UpdateArticleDto dto, int currentUserId, IEnumerable<string> currentUserRoles)
  {
    var article = await _articleRepo.GetByIdAsync(id)
        ?? throw new KeyNotFoundException("文章不存在");

    if (!article.CanEditOrDelete(currentUserId, currentUserRoles))
      throw new UnauthorizedAccessException("您无权修改此文章");

    article.UpdateContent(dto.Title, dto.Content, dto.Summary, dto.CategoryId,dto.Status);
    await _articleRepo.UpdateAsync(article);
    await _uow.SaveChangesAsync();

    return await GetArticleByIdAsync(id) ?? throw new Exception("更新失败");
  }

  public async Task DeleteArticleAsync(
      int id, int currentUserId, IEnumerable<string> currentUserRoles)
  {
    var article = await _articleRepo.GetByIdAsync(id)
        ?? throw new KeyNotFoundException("文章不存在");

    if (!article.CanEditOrDelete(currentUserId, currentUserRoles))
      throw new UnauthorizedAccessException("您无权删除此文章");

    await _articleRepo.RemoveAsync(article);
    await _uow.SaveChangesAsync();
  }
}